package main

import "fmt"

type Iterator interface {
	Next() bool
	Current() interface{}
}

type ConcreteIterator struct {
	items []string
	index int
}

func (c *ConcreteIterator) Next() bool {
	if c.index < len(c.items) {
		c.index++
		return true
	}
	return false
}

func (c *ConcreteIterator) Current() interface{} {
	if c.index > 0 && c.index <= len(c.items) {
		return c.items[c.index-1]
	}

	return nil
}

type Aggregate interface {
	CreateIterator() Iterator
}

type ConcreteAggregate struct {
	items []string
}

func (c *ConcreteAggregate) CreateIterator() Iterator {
	return &ConcreteIterator{items: c.items, index: 0}
}

func main() {
	aggregate := &ConcreteAggregate{items: []string{"A", "B", "C", "D"}}
	iterator := aggregate.CreateIterator()

	for iterator.Next() {
		fmt.Println(iterator.Current())
	}

	// Output:
	// A
	// B
	// C
	// D
}
